/**
 * -----------------------------------
 * Copyright (c) 2021-2025
 * All rights reserved, Designed By www.linfengtech.cn
 * 林风社交论坛商业版本请务必保留此注释头信息
 * 商业版授权联系技术客服	 QQ:  3582996245
 * 严禁分享、盗用、转卖源码或非法牟利！
 * 版权所有 ，侵权必究！
 * -----------------------------------
 */
package io.linfeng.modules.app.controller;


import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.exceptions.ClientException;
import io.linfeng.common.annotation.Limit;
import io.linfeng.common.annotation.NoRepeatSubmit;
import io.linfeng.common.exception.LinfengException;
import io.linfeng.common.utils.*;
import io.linfeng.common.vo.*;
import io.linfeng.common.validator.ValidatorUtils;
import io.linfeng.modules.admin.entity.AppUserEntity;
import io.linfeng.modules.admin.entity.MessageEntity;
import io.linfeng.modules.admin.entity.RechargeEntity;
import io.linfeng.modules.admin.service.ActiveUserService;
import io.linfeng.modules.admin.service.AppUserService;
import io.linfeng.modules.admin.service.RechargeService;
import io.linfeng.modules.app.annotation.Login;
import io.linfeng.modules.app.annotation.LoginUser;
import io.linfeng.modules.app.param.*;
import io.linfeng.modules.app.service.UserSettingService;
import io.linfeng.modules.app.utils.JwtUtils;
import io.linfeng.modules.app.utils.LocalUser;
import io.linfeng.modules.app.utils.SmsUtils;
import io.linfeng.modules.app.utils.tecent.TencentCloudSmsTransport;
import io.linfeng.modules.sys.service.SysConfigService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 用户登录授权
 *
 */
@RestController
@RequestMapping("/app/user")
@Api(tags = "移动端——用户登录")
public class AppUserInfoController {

    @Autowired
    private JwtUtils jwtUtils;

    @Autowired
    private AppUserService appUserService;

    @Autowired
    private RechargeService rechargeService;

    @Autowired
    private SmsUtils smsUtils;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private SysConfigService configService;

    @Autowired
    JavaMailSenderImpl mailSender;

    @Autowired
    private UserSettingService userSettingService;

    @Autowired
    private TencentCloudSmsTransport tencentCloudSmsTransport;

    @Autowired
    private ActiveUserService activeUserService;

    @Autowired
    private LocalUser localUser;

    @Value("${linfeng.email.send}")
    private String send;


    /**
     * 微信小程序登录
     * 该接口用于已绑定过手机号的账户登录
     */
    @PostMapping("/miniWxLogin")
    @ApiOperation("登录")
    public R miniWxLogin(@RequestBody WxLoginForm form, HttpServletRequest request){
        //表单校验
        ValidatorUtils.validateEntity(form);

        //用户登录
        String ip = IPUtil.getIp(request);
        Integer userId = appUserService.wxLogin(form,ip);
        if(userId==0){
            return R.error(999,"未绑定手机号");
        }
        //生成token
        String token = jwtUtils.generateToken(userId);

        Map<String, Object> map = new HashMap<>();
        map.put("token", token);
        map.put("expire", jwtUtils.getExpire());

        return R.ok(map);
    }

    /**
     * 发送验证码
     * 可配置是否开启验证码
     */
    @Limit(count = 2)
    @PostMapping("/sendSmsCode")
    @ApiOperation("发送验证码")
    public R sendSmsCode(@RequestBody SendCodeForm request){

        String code=appUserService.sendSmsCode(request);
        String smsOpen = configService.getValue(Constant.SMS_OPEN);
        if(smsOpen.equals("0")){
            String chooseSms = configService.getValue(Constant.CHOOSE_SMS);
            if(chooseSms.equals("0")){
                //发送阿里云短信
                JSONObject json = new JSONObject();
                json.put("code",code);
                try {
                    smsUtils.sendSms(request.getMobile(),json.toJSONString());
                } catch (ClientException e) {
                    String codeKey = WechatUtil.getMobileCodeKey(request.getMobile());
                    redisUtils.delete(codeKey);
                    e.printStackTrace();
                }
                return R.ok("发送成功,注意查收");
            }else{
                //发送腾讯云短信
                tencentCloudSmsTransport.sendSmsCode(request.getMobile(),code);
                return R.ok("发送成功,注意查收");
            }
        }
        return R.ok("演示验证码:"+code);
    }

    /**
     * h5登录发送验证码 先判断该手机号是否注册
     * 可配置是否开启验证码
     */
    @Limit(count = 8)
    @PostMapping("/sendLoginSmsCode")
    @ApiOperation("发送验证码判断手机号是否注册")
    public R sendLoginSmsCode(@RequestBody SendCodeForm request){
        AppUserEntity user = appUserService.lambdaQuery().eq(AppUserEntity::getMobile, request.getMobile()).one();
        if(ObjectUtil.isNull(user)){
            return R.error("该手机号未注册");
        }
        String code=appUserService.sendSmsCode(request);
        String smsOpen = configService.getValue(Constant.SMS_OPEN);
        if(smsOpen.equals("0")){
            String chooseSms = configService.getValue(Constant.CHOOSE_SMS);
            if(chooseSms.equals("0")){
                //发送阿里云短信
                JSONObject json = new JSONObject();
                json.put("code",code);
                try {
                    smsUtils.sendSms(request.getMobile(),json.toJSONString());
                } catch (ClientException e) {
                    String codeKey = WechatUtil.getMobileCodeKey(request.getMobile());
                    redisUtils.delete(codeKey);
                    e.printStackTrace();
                }
                return R.ok("发送成功,注意查收");
            }else{
                //发送腾讯云短信
                tencentCloudSmsTransport.sendSmsCode(request.getMobile(),code);
                return R.ok("发送成功,注意查收");
            }


        }
        return R.ok("演示验证码:"+code);
    }

    /**
     * 发送邮箱登录验证码
     *
     */
    @Limit(count = 8)
    @PostMapping("/sendEmailCode")
    @ApiOperation("发送邮箱登录验证码")
    public R sendEmailCode(@RequestBody SendCodeForm request){

        String code=appUserService.sendEmailCode(request);
        try {
            SimpleMailMessage mailMessage = new SimpleMailMessage();//创建一个简单的邮件信息对象
            //设置邮件发送信息的内容
            mailMessage.setSubject("林风社交论坛验证码");//标题
            mailMessage.setText("您的验证码为:" + code);//内容
            mailMessage.setFrom(send);//内容为发送方的邮箱地址
            mailMessage.setTo(request.getEmail());//内容为接收方邮箱地址
            mailSender.send(mailMessage);//发送邮件
        } catch (Exception e){
            return R.error("输入邮箱号非法");
        }

        return R.ok("发送成功,注意查收");
    }


    /**
     * 手机验证码登录
     */
    @PostMapping("/smsLogin")
    @ApiOperation("手机验证码登录")
    public R smsLogin(@RequestBody SmsLoginForm form, HttpServletRequest request){

        //用户登录
        String ip = IPUtil.getIp(request);
        Integer userId = appUserService.smsLogin(form,ip);

        //生成token
        String token = jwtUtils.generateToken(userId);

        Map<String, Object> map = new HashMap<>();
        map.put("token", token);
        map.put("expire", jwtUtils.getExpire());

        return R.ok(map);
    }

    /**
     * H5端注册并登录
     *
     */
    @PostMapping("/register")
    @ApiOperation("H5端注册")
    public R register(@RequestBody SmsLoginForm form, HttpServletRequest request){

        //用户注册并登录
        String ip = IPUtil.getIp(request);
        Integer userId = appUserService.register(form,ip);

        //生成token
        String token = jwtUtils.generateToken(userId);

        Map<String, Object> map = new HashMap<>();
        map.put("token", token);
        map.put("expire", jwtUtils.getExpire());

        return R.ok(map);
    }

    @Login
    @PostMapping("/bindEmail")
    @ApiOperation("邮箱绑定")
    public R bindEmail(@RequestBody SmsLoginForm form){
        appUserService.bindEmail(form);
        return R.ok();
    }

    @Login
    @GetMapping("/userInfo")
    @ApiOperation("获取用户信息")
    public Result<AppUserResponse> userInfo(@ApiIgnore @LoginUser AppUserEntity user){
        AppUserResponse response=appUserService.getUserInfo(user);

        return new Result<AppUserResponse>().ok(response);
    }


    @Login
    @GetMapping("userId")
    @ApiOperation("获取用户ID")
    public R userInfo(@RequestAttribute("userId") Integer userId){
        return R.ok().put("userId", userId);
    }


    @Login
    @GetMapping("userSetting")
    @ApiOperation("获取用户隐私设置")
    public Result<AppUserSettingResponse> userSetting(@ApiIgnore @LoginUser AppUserEntity user){
        AppUserSettingResponse response=userSettingService.userSetting(user.getUid());
        return new Result<AppUserSettingResponse>().ok(response);
    }


    @Login
    @PostMapping("updateUserSetting")
    @NoRepeatSubmit
    @ApiOperation("更新用户隐私设置")
    public R updateUserSetting(@ApiIgnore @LoginUser AppUserEntity user,@RequestBody UpdateUserSettingForm param){
        userSettingService.updateUserSetting(user.getUid(),param);
        return R.ok("修改成功");
    }

    @Login
    @PostMapping("/userInfoEdit")
    @ApiOperation("用户修改个人信息")
    public Result userInfoEdit(@ApiIgnore @LoginUser AppUserEntity user, @RequestBody AppUserUpdateForm appUserUpdateForm){
        ValidatorUtils.validateEntity(appUserUpdateForm);
        appUserService.updateAppUserInfo(appUserUpdateForm,user);
        return new Result().ok("修改成功");
    }


    @Login
    @PostMapping("/addFollow")
    @ApiOperation("关注用户")
    @NoRepeatSubmit
    public Result addFollow(@ApiIgnore @LoginUser AppUserEntity user, @RequestBody AddFollowForm request){
        appUserService.addFollow(request,user);
        return new Result().ok("关注用户成功");
    }


    @Login
    @PostMapping("/cancelFollow")
    @ApiOperation("取消关注用户")
    @NoRepeatSubmit
    public Result cancelFollow(@ApiIgnore @LoginUser AppUserEntity user, @RequestBody AddFollowForm request){
        appUserService.cancelFollow(request,user);
        return new Result().ok("取消关注用户成功");
    }



    @Login
    @PostMapping("/userInfoById")
    @ApiOperation("用户个人主页信息")
    public Result<AppUserInfoResponse> userInfoById(@RequestBody AppUserInfoForm request,@ApiIgnore @LoginUser AppUserEntity user){
        AppUserInfoResponse response=appUserService.findUserInfoById(request.getUid(),user);

        return new Result<AppUserInfoResponse>().ok(response);
    }

    @Login
    @GetMapping("/search")
    @ApiOperation("搜索用户")
    @NoRepeatSubmit(lockTime = 3000)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", value = "分页页码",paramType = "query", dataType = "Integer", required = true),
            @ApiImplicitParam(name = "keyword", value = "搜索关键词",paramType = "query")
    })
    public Result<AppPageUtils> search(@RequestParam("page") Integer page,
                    @RequestParam("keyword") String keyword,
                    @ApiIgnore @LoginUser AppUserEntity user){

        AppPageUtils pages =appUserService.search(page,keyword,user.getUid());
        return new Result<AppPageUtils>().ok(pages);
    }

    @Login
    @GetMapping("/userFans")
    @ApiOperation("我的粉丝分页列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", value = "分页页码",paramType = "query", dataType = "Integer", required = true),
            @ApiImplicitParam(name = "uid", value = "用户id",paramType = "query", dataType = "Integer", required = true)
    })
    public Result<AppPageUtils> userFans(@RequestParam("page") Integer page,
                                         @RequestParam("uid") Integer uid,
                                         @ApiIgnore @LoginUser AppUserEntity user){

        AppPageUtils pages =appUserService.userFans(page,uid,user.getUid());
        return new Result<AppPageUtils>().ok(pages);
    }

    @Login
    @GetMapping("/follow")
    @ApiOperation("我的关注分页列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page", value = "分页页码",paramType = "query", dataType = "Integer", required = true)
    })
    public Result<AppPageUtils> follow(@RequestParam("page") Integer page,
                                       @RequestParam("uid") Integer uid,
                                       @ApiIgnore @LoginUser AppUserEntity user){

        AppPageUtils pages =appUserService.follow(page,uid,user);
        return new Result<AppPageUtils>().ok(pages);
    }


    @GetMapping("/recharge/list")
    @ApiOperation("用户充值方案")
    public Result<List<RechargeEntity>> recharge(){

        List<RechargeEntity> allRecharge = rechargeService.getAllRecharge();
        return new Result<List<RechargeEntity>>().ok(allRecharge);
    }

    @GetMapping("/isOpen")
    @ApiOperation("是否开启视频入口")
    public Result isOpen(){
        String isOpen = configService.getValue(Constant.IS_OPEN);
        if(isOpen.equals("1")){
            return new Result<>().ok(1);
        }
        return new Result<>().ok(0);
    }

    @Login
    @GetMapping("/getContact")
    @ApiOperation("客服联系方式")
    public Result<Object> getContact(){
        String contactWeChat = configService.getValue(Constant.CONTACT_WECHAT);
        String contactWeChatQr = configService.getValue(Constant.CONTACT_WECHAT_QR);
        String time = configService.getValue(Constant.CONTACT_TIME);
        String phone = configService.getValue(Constant.CONTACT_PHONE);
        Map<String,String> map=new HashMap<>();
        map.put("wechat",contactWeChat);
        map.put("image",contactWeChatQr);
        map.put("time",time);
        map.put("phone",phone);
        return new Result<>().ok(map);
    }

    @Login
    @PostMapping("/systemInfoList")
    @ApiOperation("系统消息列表")
    public R systemInfoList(@RequestBody ChatListForm request,@ApiIgnore @LoginUser AppUserEntity user){
        List<MessageEntity> list=appUserService.systemInfoList(request,user);
        return R.ok().put("result", list);
    }

    @GetMapping("/getHotUserList")
    @ApiOperation("热门博主列表")
    public Result<List<AppHotUserResponse>> getHotUserList(){
        List<AppHotUserResponse> list=appUserService.getHotUserList();
        return new Result<List<AppHotUserResponse>>().ok(list);
    }

    @PostMapping("/getSessionKey")
    @NoRepeatSubmit
    @ApiOperation(value = "获取微信加密秘钥")
    public R getSessionKey(@RequestBody  WxLoginForm param){
        String appId = configService.getValue(Constant.WX_APP_ID);
        String appSecret = configService.getValue(Constant.WX_APP_Secret);
        JSONObject json = WechatUtil.getSessionKeyOropenid(param.getCode(),appId,appSecret);
        String session_key = json.getString("session_key");
        String openid = json.get("openid").toString();
        return R.ok().put("session_key",session_key).put("openid",openid);
    }

    @PostMapping("/bindWxPhone")
    @ApiOperation("微信小程序绑定手机号")
    public Result<Object> bindWxPhone(@RequestBody LoginPhoneParam param,HttpServletRequest request){
        String ip = IPUtil.getIp(request);
        Integer userId = appUserService.bindWxPhone(param,ip);//如果手机号已被注册过则返回0
        String token = jwtUtils.generateToken(userId);
        Map<String, Object> map = new HashMap<>();
        map.put("token", token);
        map.put("expire", jwtUtils.getExpire());
        return new Result<>().ok(map);
    }

    @Login
    @PostMapping("/removeTopic")
    @ApiOperation("用户移除圈子")
    public Result removeTopic(@ApiIgnore @LoginUser AppUserEntity user, @RequestBody RemoveTopicForm request){
        appUserService.removeTopic(request,user);
        return new Result().ok("移除成功");
    }


    @Login
    @GetMapping("/getUserLevelInfo")
    @ApiOperation("获取用户等级信息")
    public R getHotUserList(@ApiIgnore @LoginUser AppUserEntity user){
        Map<String, Object> map = appUserService.getUserLevelInfo(user);
        return R.ok().put("result",map);
    }

    /**
     * 是否有微信公众号openID
     * @return 是否有微信公众号openID
     */
    @Login
    @GetMapping("/hasMpOpenid")
    @ApiOperation("是否有微信公众号openid")
    public R hasMpOpenid(@ApiIgnore @LoginUser AppUserEntity user){
        return R.ok().put("result", !WechatUtil.isEmpty(user.getMpOpenid()));
    }

    /**
     * 微信公众号openid绑定
     * @param request 登录请求
     * @return 绑定结果
     */
    @Login
    @PostMapping("/bindMpOpenid")
    @ApiOperation("微信公众号openid绑定")
    public R mpWxLogin(@ApiIgnore @LoginUser AppUserEntity user,  @RequestBody WxMpLoginForm request){

        appUserService.bindMpOpenid(user, request);

        return R.ok();
    }

    /**
     * 微信公众号检查code是否注册，注册过自动登录
     * @param param 登录请求
     * @return 绑定结果
     */
    @PostMapping("/loginByWxMp")
    @ApiOperation("微信公众号code登录")
    public R loginByWxMp(@RequestBody WxMpLoginForm param, HttpServletRequest request){

        String ip = IPUtil.getIp(request);
        Integer userId = appUserService.loginByWxMp(param, ip);
        if(userId==0){
            return R.error(501,"未注册用户");
        }
        //生成token
        String token = jwtUtils.generateToken(userId);
        Map<String, Object> map = new HashMap<>();
        map.put("token", token);
        map.put("expire", jwtUtils.getExpire());

        return R.ok(map);
    }


    @ApiOperation("用户端——统计当前用户")
    @PostMapping("/visitor")
    public R visitor(@RequestBody VisitorForm param,HttpServletRequest request){
        String ip = IPUtil.getIp(request);
        AppUserEntity user = localUser.getUser();
        activeUserService.addVisit(ip,param,user);
        return R.ok();
    }


    @PostMapping("/userRank")
    @ApiOperation("发帖达人列表")
    public R userRank() {
        List<AppUserRankResponse> list=appUserService.userRank();
        return R.ok().put("result",list);
    }


    /**
     * 第三方应用请求登录
     * @param form
     * @param request
     * @return
     */
    @PostMapping("/thirdLogin")
    @ApiOperation("第三方应用请求登录接口")
    public R getToken(@RequestBody UserLoginForm form, HttpServletRequest request){
        String ip = IPUtil.getIp(request);
        Integer userId = appUserService.getThirdLoginToken(form,ip);
        String token = jwtUtils.generateToken(userId);
        Map<String, Object> map = new HashMap<>();
        map.put("token", token);
        map.put("expire", jwtUtils.getExpire());

        return R.ok(map);
    }
}
